home *** CD-ROM | disk | FTP | other *** search
- name msxrb1
- ; File msxrb1.asm
- include mssdef.h
- ; Copyright (C) 1982,1991, Trustees of Columbia University in the
- ; City of New York. Permission is granted to any individual or
- ; institution to use, copy, or redistribute this software as long as
- ; it is not sold for profit and this copyright notice is retained.
- ; Kermit system dependent module for Rainbow
- ; Jeff Damens, July 1984
- ; with additional major changes by Joe Doupnik, 1986, 1987, 1988, 1989, 1991
- ; Edit history:
- ; 2 March 1991 version 3.10
- ; Last edit 1 March 1991
- ; 27-AUG-1990 [rhw]
- ; 27-AUG-1990 I had added shr cx,1 to divide the CX=swidth by 2
- ; but swidth is a const so I removed the shifts & simply
- ; divided the const by 2. This saves an shift in many places.
- ; [rhw-5] Robert H. Weiner
- ; 25-AUG-1990 Replaced MOVSB with MOVSW for all screen ops
- ; Divide counts by 2 1st for byte to word conversion
- ; Since swidth is always even, this can save alot of cycles:
- ; REP MOVSB -> MOVSW should save 17*132/2=1122 cycles for
- ; swidth char moves since iteration count is cut in half.
- ; [rhw-4] Robert H. Weiner
- ; 24-AUG-1990 Added print screen character XLAT table to make all the
- ; VT100 char graphics come out on a normal printer, xlat_tab[]
- ; Added same XLAT code to dumpscr code since that too is
- ; a real mess without it. Now linedraw boxes look like boxes.
- ; Added SETCHTAB definition that's now required in machine
- ; specific modules
- ; [rhw-3] Robert H. Weiner
- ; Present-
- ; 01-JUL-1990 MSYIBM.ASM screen rollback routines merged into MSXRB1.ASM
- ; This should speed up rollback screen handling
- ; Sorry, this code left out of this source release since its
- ; presently incomplete.
- ; [rhw-2] Robert H. Weiner
- ; MAY-1990 connect mode hangup (^]-H) fixed (needed delay) RHW/JRD
- ; [rhw-1] Robert H. Weiner (robert%progplus.uucp@uunet.uu.net)
- ; 30-Apr-1990 fix baud rate return [gbs]
- ; convert unprintable characters to "." in print screen
- ; 14-Feb-1990 fix VT102 initialization. gbs
- ; 11 Nov Revise for MS Kermit version 3. jrd
- ; 11-Nov-1989 reversed print controller/autoprint.
- ; Had it wrong the first time.
- ; Gary B. Stebbins
- ; 18-Oct-1989 added minimal print controller support & autoprint
- ; (module needs cleanup in incoming character handling)
- ; (print stuff doesn't handle DECEXT or DECPFF)
- ; (really kludged in...should be rewritten similar to
- ; input character handling for IBM PC)
- ; Gary B. Stebbins
- ; 4-Mar-1989 several problems related to modem signal handling fixed.
- ; Gary B. Stebbins, Don Metz
- ; 1 July 1988 Version 2.31
- ; 10 Jan 1988 Cleanup 8 bit display in outtty. [jrd]
- ; 1 Jan 1988 version 2.30
-
- public serini, serrst, clrbuf, outchr, coms, vts, vtstat, dodel
- public ctlu, cmblnk, locate, lclini, prtchr, dobaud, clearl
- public getbaud, beep, pcwait, dumpscr, termtb, shomodem
- public count, xofsnt, puthlp, putmod, clrmod, poscur, getmodem
- public sendbr, sendbl, term, machnam, setktab, setkhlp, showkey
- public ihosts, ihostr, serhng, dtrlow, comptab, baudst
- ; action verb procedures for keyboard translator
- public prvscr, nxtscr, prtscn
- public uparrw, dnarrw, rtarr, lfarr, pf1, pf2, pf3, pf4
- public kp0, kp1, kp2, kp3, kp4, kp5, kp6, kp7, kp8, kp9
- public kpminus, kpcoma, kpenter, kpdot, chrout, cstatus, cquit
- public cquery, prvscr, nxtscr, prvlin, nxtlin, trnprs, snull
- public nxttop, nxtbot, klogon, klogof, cdos, chang
- public portval, bdtab, setchtab
-
- ; rainbow-dependent screen constants
-
- scrseg equ 0ee00H ; screen segment
- latofs equ 0ef4h ; ptrs to line beginnings, used by firmware
- l1ptr equ latofs ; ptr to first line
- llptr equ latofs+23*2 ; ptr to last line
- csrcol equ 0f41h ; current cursor column
- csrlin equ 0f42h ; current cursor line
- curlin equ 0f43h ; current line flags
- wrpend equ 2 ; wrap pending
- attoffs equ 1000H
- rmargin equ 0f57h ; right margin limit
-
- ; rainbow-dependent firmware locations
- nvmseg equ 0ed00h ; segment containing NVM
- xmitbd equ 0a1h ; address of xmit baud
- rcvbd equ 0a2h ; " " receive baud
- autwrp equ 08dH ; b0 = 1 if auto wrap on (?)
- newlmod equ 08eh ; b0 = 0 lf, = 1 newline (cr/lf)
- bdprt equ 06h ; baud rate port
- vt52mod equ 088h ; b0 = 1 if in ansi mode
- off equ 0
- bufon equ 1 ; buffer level xon/xoff on-state control flag
- usron equ 2 ; user level xon/xoff on-state control flag
-
- mntrgh equ bufsiz*3/4 ; High point = 3/4 of buffer full
- mntrgl equ bufsiz/4 ; Low point = 1/4 buffer full
-
- mnstata equ 042H ; Status/command port A
- mnstatb equ 043H ; Status/command port B
- mndata equ 040H ; Data port
- mndatb equ 041H
- mnctrl equ 002H ; Control port
- serchn equ 0A4H ; interrupt to use
- serch1 equ 044H ; use this too for older rainbows
-
- txrdy EQU 04H ;Bit for output ready
- rxrdy EQU 01H ;Bit for input ready
-
- fastcon equ 29H ; fast console handler
- firmwr equ 18H ; Bios interrupt
- kcurfn equ 8h ; disable cursor
- rcurfn equ 0ah ; enable cursor
-
- swidth equ 132 ; screen width
- slen equ 24 ; screen length
- npages equ 10 ; for use with dynamic memory allocation
-
- stbrk equ 15 ; start sending a break
- enbrk equ 16 ; stop sending break
-
- ; external variables used:
- ; flags - global flags as per flginfo structure defined in pcdefs
- ; trans - global transmission parameters, trinfo struct defined in pcdefs
- ; portval - pointer to current portinfo structure (currently either port1
- ; or port2)
- ; port1, port2 - portinfo structures for the corresponding ports
-
- ; global variables defined in this module:
- ; xofsnt, xofrcv - tell whether we saw or sent an xoff.
-
- ; circular buffer ptr
- cbuf struc
- pp dw ? ; place ptr in buffer
- bend dw ? ; end of buffer
- orig dw ? ; buffer origin
- lcnt dw 0 ; # of lines in buffer
- lmax dw ? ; max lines of buffer
- cbuf ends
-
- ; answerback structure
- ans struc
- anspt dw ? ; current pointer in answerback
- ansct db ? ; count of chars in answerback
- ansseq dw ? ; pointer to whole answerback
- anslen db ? ; original length
- ansrtn dw ? ; routine to call
- ans ends
-
- ; structure for status information table sttab.
- stent struc
- sttyp dw ? ; type (actually routine to call)
- msg dw ? ; message to print
- val2 dw ? ; needed value: another message, or tbl addr
- tstcel dw ? ; address of cell to test, in data segment
- basval dw 0 ; base value, if non-zero
- stent ends
-
- data segment public 'data'
- extrn flags:byte, trans:byte, filtst:byte, dmpname:byte
- extrn rxtable:byte, kbdflg:byte, repflg:byte, diskio:byte
- extrn ttyact:byte, denyflg:word, prnhand:word
-
- ; [rhw-3] Start Definitions for Print Screen Translation Table
- xlat_tab_size equ 32 ; chars 00 through 31 decimal
- ; 0=null, 1=diamond, 2=blob, 3=HT, 4=FF, 5=CR, 6=LF, 7=degree, 8=+/-
- ; 9=NL, 10=VT, 11=low_rt_corner, 12=up_rt_corner, 13=up_left_corner,
- ; 14=low_left_corner, 15=cross, 16...20=horiz_line_scan1,3,5,7,9
- ; 21=left_t, 22=right_t, 23=bott_t, 24=top_t, 25=vertical, 26=<=
- ; 27=>=, 28=pi, 29=<>, 30=pound, 31=centered_dot
- ; 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7
- xlat_tab db ' ', '*', '#', '.', '.', '.', '.', 'o'
- ; 8 , 9 , 10, 11, 12, 13, 14, 15
- db '+', '.', '.', '+', '+', '+', '+', '+'
- ; 16, 17, 18, 19, 20, 21, 22, 23
- db '_', '_', '-', '-', '-', '+', '+', '+'
- ; 24, 25, 26, 27, 28, 29, 30, 31
- db '+', '|', '<', '>', 'p', '!', '#', '.'
- ; [rhw-3] End Print Screen Translation Table
-
- setchtab db 1 ; [rhw-3] Set File Character-Set table
- mkeyw 'VT102',0 ; [rhw-3] hardware default Code Page
- ;; mkeyw 'User-defined',1 ; User loadable table
-
-
- setktab db 0
- akeyflg db 0 ; non-zero if in alt keypad mode
- ckeyflg db 0 ; non-zero if cursor is in applications mode
- ourflgs db 0 ; our flags
- fpscr equ 80H ; flag definitions
- vtautop equ 1 ; autoprint enabled
- vtcntp equ 2 ; controller print enabled
- fairness dw 0 ; keyboard/port sharing counter
- dupflg db 0 ; full (0) or half (1) duplex on port
- argadr dw 0 ; pointer to arguments from msster
- crlf db cr,lf,'$'
- setkhlp db 0
- machnam db 'Rainbow$'
- nyimsg db cr,lf,'Not yet implemented$'
- dmperr db cr,lf,'?Cannot access screen-dump file$',cr,lf
- hngmsg db cr,lf,' The phone should have hungup.',cr,lf,'$'
- hnghlp db cr,lf,' The modem control lines DTR and RTS for the current'
- db ' port are forced low (off)'
- db cr,lf,' to hangup the phone. Normally, Kermit leaves them'
- db ' high (on) when it exits.'
- db cr,lf,'$'
- msmsg1 db cr,lf,' Modem is not ready: DSR is off$'
- msmsg2 db cr,lf,' Modem is ready: DSR is on$'
- msmsg3 db cr,lf,' no Carrier Detect: CD is off$'
- msmsg4 db cr,lf,' Carrier Detect: CD is on$'
- msmsg5 db cr,lf,' no Clear To Send: CTS is off$'
- msmsg6 db cr,lf,' Clear To Send: CTS is on$'
- rdbuf db swidth dup (?) ; temp buf
- delstr db BS,BS,' ',BS,BS,'$' ; Delete string
- clrlin db cr,'$' ; Clear line (just the cr part)
- oldser dw ? ; old serial handler
- oldseg dw ? ; segment of above
- old1ser dw ? ; old serial handler, alternate address
- old1seg dw ? ; segment of same
- portin db 0 ; Has comm port been initialized
- mdstreg db 0 ; Modem line status report for Show Modem
- xofsnt db 0 ; Say if we sent an XOFF
- xofrcv db 0 ; Say if we received an XOFF
- parmsk db 0ffh ; 7-8 bit parity mask
- flowon db 0 ; flow on char (xon or null)
- flowoff db 0 ; flow off char (xoff or null)
- mdmhand db 0 ; Modem status register, current
- iobuf db 5 dup (?) ; buffer for ioctl
-
- gopos db escape,'['
- rowp db 20 dup (?)
- clrseq db escape,'[H',escape,'[J$'
- ceolseq db escape,'[K$'
- invseq db escape,'[7m$'
- nrmseq db escape,'[0m$'
- ivlatt db swidth dup (0fH) ; a line's worth of inverse attribute
- dumpbuf db swidth+2 dup (?) ; screen dump work buffer
- dumpsep db FF,cr,lf ; screen dump image separator
- dovt52 db escape,'[?2l$' ; set VT52 mode
- dovt102 db escape,'<$' ; set VT102 mode
-
- ourarg termarg <>
- comptab db 2 ; communications port options
- mkeyw '1',1
- mkeyw 'COM1',1 ; only one option here
-
- ontab db 2
- mkeyw 'off',0
- mkeyw 'on',1
-
- vttbl db 3 ; SET TERM table
- mkeyw 'Roll',10
- mkeyw 'VT102',ttvt100
- mkeyw 'VT52',ttvt52
-
- termtb db 2 ; entries for Status, not Set
- mkeyw 'VT102',ttvt100
- mkeyw 'VT52',ttvt52
-
- rolhlp db cr,lf,' Roll (undo screen roll back before writing new'
- db ' chars, default=off)$'
-
- vtrolst db 'Term rollback: $'
-
- vtstbl stent <srchkw,vtrolst,ontab,vtroll> ; rollback
- dw 0 ; end of table
-
-
-
- ; variables for serial interrupt handler
- source db bufsiz DUP(?) ; Buffer for data from port
- srcpnt dw source ; Pointer in buffer (DI)
- count dw 0 ; Number of chars in int buffer
- telflg db 0 ; non-zero if we're a terminal. NRU
- ivec dw tranb ; transmit empty B
- dw tranb ; status change B
- dw tranb ; receive b
- dw tranb ; special receive b
- dw stxa ; transmit empty a
- dw sstata ; status change a
- dw srcva ; receive a
- dw srcva ; special receive a
-
- ; baud rate definitions
- ; value is programmed into baud rate port
- bdtab db 16 ; Baud rate table
- mkeyw '50',0
- mkeyw '75',1
- mkeyw '110',2
- mkeyw '134.5',3
- mkeyw '150',4
- mkeyw '200',5
- mkeyw '300',6
- mkeyw '600',7
- mkeyw '1200',8
- mkeyw '1800',9
- mkeyw '2000',10
- mkeyw '2400',11
- mkeyw '3600',12
- mkeyw '4800',13
- mkeyw '9600',14
- mkeyw '19200',15
-
- ; multi-screen stuff
- twnd cbuf <> ; top screen spill-buffer struct
- bwnd cbuf <> ; bottom screen spill buffer struct
- topline dw swidth dup (?) ; top line screen spill buffer
- botline dw swidth dup (?) ; bottom line screen spill buffer
- rlbuf dw swidth dup (?) ; temp buffer for line scrolling
- scrnbuf db swidth*slen dup (?) ; save-screen, text
- attrbuf db swidth*slen dup (?) ; save-screen, attributes
- srcseg dw 0
-
- topdwn db escape,'[H',escape,'M$' ; go to top, scroll down
- botup db escape,'[24;0H',escape,'D$' ; go to bottom, scroll up
- curinq db escape,'[6n$' ; cursor inquiry
- posbuf db 20 dup (?) ; place to store cursor position
- gtobot db escape,'[24;0H$' ; go to bottom of screen
- ourscr dw ?
- ourattr dw ? ; storage for screen and attributes
- inited db 0 ; terminal handler not inited yet
- dosmsg db '?Must be run in version 2.05 or higher$'
- dmphand dw ? ; file handle for screen dump
- anssq1 db escape,'[c'
- an1len equ $-anssq1
- anssq2 db escape,'Z'
- an2len equ $-anssq2
- eakseq db escape,'='
- eaklen equ $-eakseq
- dakseq db escape,'>'
- daklen equ $-dakseq
- cuapseq db escape,'[?1h'
- cuaplen equ $-cuapseq
- cunapseq db escape,'[?1l'
- cunaplen equ $-cunapseq
- crsseq db escape,'c'
- crslen equ $-crsseq
- enqseq db escape,'[6n'
- enqlen equ $-enqseq
- apenable db escape,'[?5i' ;autoprint enable
- apenlen equ $-apenable
- apdisabl db escape,'[?4i' ;autoprint disable
- apdislen equ $-apdisabl
- pcenable db escape,'[5i' ;print controller enable
- pcenlen equ $-pcenable
- pcdisabl db escape,'[4i' ;print controller disable
- pcdislen equ $-pcdisabl
- pscrn0 db escape,'[i' ;print screen
- psc0len equ $-pscrn0
- pscrn1 db escape,'[0i' ;print screen
- psc1len equ $-pscrn1
-
- ansbk1 ans <anssq1,an1len,anssq1,an1len,sndans> ; two answerbacks
- ansbk2 ans <anssq2,an2len,anssq2,an2len,sndans>
- ansbk3 ans <eakseq,eaklen,eakseq,eaklen,enaaky> ; enable alt keypad
- ansbk4 ans <dakseq,daklen,dakseq,daklen,deaaky> ; disable alt keypad
- ansbk5 ans <crsseq,crslen,crsseq,crslen,sndspc> ; crash sequence (!)
- ansbk6 ans <enqseq,enqlen,enqseq,enqlen,ansenq>
- ansbk7 ans <cuapseq,cuaplen,cuapseq,cuaplen,cuapp> ; cursor application
- ansbk8 ans <cunapseq,cunaplen,cunapseq,cunaplen,cunapp>; cursor cursor
- ansbk9 ans <apenable,apenlen,apenable,apenlen,apon>; autoprint enable
- ansbk10 ans <apdisabl,apdislen,apdisabl,apdislen,apoff>;autoprint disable
- ansbk11 ans <pcenable,pcenlen,pcenable,pcenlen,prconon>;print control on
- ansbk12 ans <pcdisabl,pcdislen,pcdisabl,pcdislen,pconoff>;print control off
- ansbk13 ans <pscrn0,psc0len,pscrn0,psc0len,prtscn> ; print screen
- ansbk14 ans <pscrn1,psc1len,pscrn1,psc1len,prtscn> ; print screen
-
- ansret db escape,'[?6c'
- db 10 dup (?)
- ansrln equ $-ansret
- vt52ret db escape,'/Z' ; VT52 identification
- vt52ln equ $-vt52ret
- temp dw 0
- vtroll db 0
-
- port1 prtinfo <0FFFH,0,defpar,1,0,defhand,floxon,0>
- portval dw port1 ; Default is to use port 1
-
- ;port initialization data for 7201 [ejz]
- ;enables Rx,Tx, CTS, DTR, 8 bits, no parity, 1.5 stop bits
- prtpar db 18H,14H,48H,13H,0C1H,15H,0EAH,11H,18H,00H
-
- data ends
-
- code segment public 'code'
- extrn comnd:near, dopar:near, sleep:near, sbrk:near, isfile:near
- extrn strlen:near, strcpy:near, msuinit:near, keybd:near
- extrn statc:near, srchkw:near, pntchr:near, pntflsh:near
-
- assume cs:code, ds:data, es:nothing
-
- ; local initialization routine, called by Kermit initialization.
-
- lclini proc near
- mov ah,dosver ; make sure this is DOS version 2.05 or higher
- int dos
- xchg al,ah ; put major version in ah, minor in al
- cmp ax,205H ; is it 2.05?
- jae lclin1 ; yes, go on
- mov dx,offset dosmsg
- call tmsg
- cmp flags.extflg,1 ; exit now
- ret
- lclin1: mov flags.vtflg,ttvt100 ; default to VT102
- call setterm ; set terminal type to VT102
- call msuinit ; initialize keyboard translator
- mov ourscr,offset scrnbuf ; save-screen text buf address
- mov ourattr,offset attrbuf ; save-screen attr buf address
-
- mov ax,swidth*2*2 ; ask for two lines (1 per buffer)
- call sbrk ; allocate mem. Exit Kermit on failure
- ;if we get here them we have the lines
- mov bwnd.orig,ax ; memory segment, bottom window area
- mov twnd.orig,ax ; top. same place for both buffers!
- push es ; save this register
- mov es,ax ; seg pointer to new memory block
- mov bx,(swidth*slen*npages+7)/8 ; paragraphs wanted for roll back
- add bx,24000D/16 ; plus paragraphs to run Command.com
- mov ah,setblk ; DOS Setblock. Ask for that space
- int dos ; bx has # paragraphs available
- sub bx,24000D/16 ; deduct space for DOS 3.x Command.Com
- cmp bx,(swidth*4+15)/16 ; any room left for buffers?
- jae lclyin2 ; some space is available for buffers
- mov bx,(swidth*4+15)/16 ; else use our sbrk allocation
- lclyin2:mov ah,setblk ; ask for that many (bx) paragraphs
- int dos ; Errors here == DOS deceived us
- pop es ; restore reg
- mov ax,bx ; bx = # paragraphs allocated by DOS
- mov cl,3 ; 2**3 = 8
- shl ax,cl ; paragraphs to words (char + attrib)
- xor dx,dx ; clear extended size
- mov cx,swidth ; number of chars per line in buffer
- div cx ; ax = number of lines in buffer
- mov bwnd.lmax,ax ; max lines per buffer (quotient)
- mov twnd.lmax,ax ; max lines per buffer
- add cx,cx ; count char and attribute per item
- xor dx,dx ; clear extended numerator
- mul cx ; ax = effective # bytes per buffer
- dec ax ; adjust for counting from zero
- mov bwnd.bend,ax ; offset of last byte in buffer
- mov twnd.bend,ax ; offset of last byte in buffer
- mov bwnd.pp,0 ; offset of first byte in buffer
- mov twnd.pp,0 ; offset of first byte in buffer
- mov bwnd.lcnt,0 ; number of lines occupied in buffer
- mov twnd.lcnt,0 ; number of lines occupied in buffer
- or denyflg,tekxflg ; deny automatic Tektronix invokation
- ret
- lclini endp
-
- ; show the definition of a key. The terminal argument block (which contains
- ; the address and length of the definition tables) is passed in ax.
- ; Returns a string to print in AX, length of same in CX.
- ; Returns normally.
- showkey proc near
- ret
- showkey endp
-
-
- ; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
- ; Uses byte mdmhand, the modem line status register. [jrd]
- shomodem proc near
- mov ah,cmeol ; get a confirm
- call comnd
- jc shomd5 ; c = failure
- call getmodem ; get modem status
- mov mdmhand,al
- mov ah,prstr
- mov dx,offset msmsg1 ; modem ready msg
- test mdmhand,20h ; is DSR asserted?
- jz shomd1 ; z = no
- mov dx,offset msmsg2 ; say not asserted
- shomd1: int dos
- mov dx,offset msmsg3 ; CD asserted msg
- test mdmhand,80h ; CD asserted?
- jz shomd2 ; z = no
- mov dx,offset msmsg4 ; say not asserted
- shomd2: int dos
- mov dx,offset msmsg5 ; CTS asserted msg
- test mdmhand,10h ; CTS asserted?
- jz shomd3 ; z = no
- mov dx,offset msmsg6 ; say not asserted
- shomd3: mov ah,prstr
- int dos
- clc
- shomd5: ret
- shomodem endp
-
- ; Get modem status and set global byte mdmhand. Preserve all registers.
- ; Uses byte mdstreg, the modem line status register, bits as follows:
- ; Int Z80, Int 8088, Hwd fail det enable, CD, CTS, DSR, SI/SecCD, RI [jrd]
- getmodem proc near ; gets modem status upon request
- push dx
- mov al,0 ; assume nothing is on
- mov dx,mnctrl ; modem control port (read 02h)
- in al,dx ; read modem control port
- not al ; invert RB modem bits (0=true) [gbs]
- mov mdmhand,0 ; clear status byte
- test al,4 ; DSR asserted?
- jz getmod1 ; z = no
- or mdmhand,20h ; set IBM spec DSR bit
- getmod1:test al,8 ; CTS asserted?
- jz getmod2 ; z = no
- or mdmhand,10h ; set IBM spec CTS bit
- getmod2:test al,10h ; CD asserted? [gbs]
- jz getmod3 ; z = no
- or mdmhand,80h ; set IBM spec CD bit [gbs]
- getmod3:mov al,mdmhand ; setup return
- mov ah,0 ; return status in al
- pop dx
- clc
- ret
- getmodem endp
-
- ; Clear the input buffer. This throws away all the characters in the
- ; serial interrupt buffer. This is particularly important when
- ; talking to servers, since NAKs can accumulate in the buffer.
- ; Returns normally.
-
- CLRBUF PROC NEAR
- cli
- mov srcpnt,offset source
- mov count,0
- sti
- ret
- CLRBUF ENDP
-
- ; Clear to the end of the current line. Returns normally.
-
- CLEARL PROC NEAR
- mov dx,offset ceolseq ; clear sequence
- jmp tmsg
- CLEARL ENDP
-
-
- ; Put the char in AH to the serial port, assumimg the port is active.
- ; Returns carry clear if success, else carry set.
- ; 16 May 1987 Add entry point OUTCH2 for non-flow controlled sending to
- ; prevent confusion of flow control logic at top of outchr; used by receiver
- ; buffer high/low water mark flow control code. [jrd]
- OUTCHR PROC NEAR
- cmp flowoff,0 ; Are we doing flow control
- je outch2 ; No, just continue
- cmp ah,flowoff ; sending xoff?
- jne outch1 ; ne = no
- mov xofsnt,usron ; indicate user level xoff being sent
- jmp outch1b
- outch1:
- and xofsnt,not usron ; cancel user level xoff
- cmp ah,flowon ; user sending xon?
- jne outch1b ; ne = no
- mov xofsnt,off ; say an xon has been sent (cancels xoff)
- outch1b:cmp xofrcv,off ; Are we being held (xoff received)?
- je outch2 ; e = no - it's OK to go on
- cmp ttyact,0 ; in Connect mode?
- je outch1d ; e = no
- call beep ; let user know we are xoff-ed
- mov xofrcv,off ; force off XOFF (unblock output)
- jmp outch2 ; and send the char anyway
- outch1d:cmp flags.timflg,0 ; is timer off?
- je outch2 ; e = yes, no timeout period
- push cx ; save reg
- mov ch,trans.rtime ; receive timeout interval (sec)
- xor cl,cl ; convert to 4 millsec increments
- jcxz outch1c ; z = no timeout wanted
-
- outch1a:cmp xofrcv,off ; Are we being held (xoff received)?
- je outch1c ; e = no - it's OK to go on
- push ax
- mov ax,4 ; 4 millisec wait loop
- call pcwait
- pop ax
- loop outch1a ; and try it again
- mov xofrcv,off ; timed out, force it off and fall thru
- outch1c:pop cx ; end of flow control section
- ; OUTCH2 is entry point for sending without flow control
- OUTCH2: mov al,ah ; Parity routine works on AL
- call dopar ; Set parity appropriately
- mov ah,al ; Don't overwrite character with status
- cmp repflg,0 ; doing REPLAY from a file?
- je outch3 ; e = no
- and al,7fh ; strip parity
- cmp al,'C'-40h ; Control-C? (to exit playback mode)
- je outch2a ; e = yes, return failure
- clc ; return success, send nothing
- ret
- outch2a:stc ; return failure to exit playback mode
- ret
- outch3: push cx ; save registers
- push dx
- outch3b:cmp dupflg,0 ; full duplex?
- je outch3d ; e = yes
- mov al,0f1h ; enable RTS and DTR Note: bits reversed [gbs]
- out mnctrl,al ;[DTR] compared to documentation
- in al,mnctrl
- test al,4 ; ignore CTS if DSR is not asserted
- jz outch3d ; z = DSR not asserted
- mov cx,8000 ; ~10 seconds worth of waiting on CTS
- outch3c:in al,mnctrl
- test al,8 ; is CTS asserted?
- jnz outch3d ; nz = yes
- push cx
- push dx
- mov ax,1 ; wait one millisec
- call pcwait
- pop dx
- pop cx
- loop outch3c ; test again
- call beep ; half duplex timeout, make non-fatal
- pop dx
- pop cx
- clc
- ret
-
- outch3d:xor cx,cx
- mov dx,mnstata ; get port status
- in al,dx
- test al,txrdy ; transmitter ready?
- jnz outch4 ; nz = yes
- jmp $+2 ; use time, prevent overdriving UART
- loop outch3b
- jmp outch5 ; timeout
- outch4: mov al,ah ; send it out
- mov dx,mndata ; use a little time
- jmp $+2
- out dx,al
- cmp dupflg,0 ; full duplex?
- je outch4a ; e = yes
- cmp al,trans.seol ; End of Line char?
- jne outch4a ; ne = no
- mov al,0f5h ; disable RTS (4)
- out mnctrl,al
- outch4a:pop dx ; exit success
- pop cx
- clc
- ret
- outch5: call beep
- pop dx ; exit failure
- pop cx
- stc
- ret
- OUTCHR ENDP
-
- ; This routine blanks the screen.
-
- CMBLNK PROC NEAR
- mov dx,offset clrseq ; clear screen sequence
- jmp tmsg
- CMBLNK ENDP
-
- ; Locate; homes the cursor. Returns normally.
-
- LOCATE PROC NEAR
- xor dx,dx ; Go to top left corner of screen
- jmp poscur
- LOCATE ENDP
-
- ; write a line in inverse video at the bottom of the screen...
- ; the line is passed in dx, terminated by a $. Returns normally.
- putmod proc near
- push dx ; preserve message
- mov dx,24 * 100H ; line 24
- call poscur
- mov dx,offset invseq ; put into inverse video
- call tmsg
- pop dx
- call tmsg ; print the message
- mov dx,offset nrmseq ; normal videw
- call tmsg
- ret ; and return
- putmod endp
-
- ; clear the mode line written by putmod. Returns normally.
- clrmod proc near
- mov dx,24 * 100H
- call poscur
- jmp clearl
- clrmod endp
-
- ; Put a help message on the screen. This one uses reverse video...
- ; pass the message in ax, terminated by a null. Returns normally.
- puthlp proc near
- push ax
- mov dx,slen * 100H ; go to bottom line
- call poscur
- pop ax
- push es
- mov bx,ds
- mov es,bx ; address data segment
- mov si,ax ; convenient place for this
- mov bx,101H ; current line/position
- puthl1: mov di,offset rdbuf ; this is destination
- xor cx,cx ; # of chars in the line
- cld
- puthl2: lodsb ; get a byte
- cmp al,cr ; carriage return?
- je puthl2 ; yes, ignore it
- cmp al,lf ; linefeed?
- je puthl3 ; yes, break the loop
- cmp al,0
- je puthl3 ; ditto for null
- dec cx ; else count the character
- stosb ; deposit into the buffer
- jmp puthl2 ; and keep going
- puthl3: add cx,80 ; this is desired length of the whole
- mov al,' '
- rep stosb ; fill the line
- push bx
- push si
- push es ; firmware likes to eat this one
- mov ax,0 ; send chars and attributes
- mov cx,80 ; this is # of chars to send
- mov dx,offset ivlatt ; this are attributes to send
- mov si,offset rdbuf ; the actual message
- mov di,14H ; send direct to screen
- mov bp,ds ; need data segment as well
- push ax
- push cx
- push dx
- push di
- mov di,14H ; send direct to screen
- int firmwr
- pop di
- pop dx
- pop cx
- pop ax
- pop es
- pop si
- pop bx ; restore everything
- inc bx ; next line
- cmp byte ptr [si-1],0 ; were we ended by a 0 last time?
- jne puthl1 ; no, keep looping
- pop es ; else restore this
- clc
- ret ; and return
- puthlp endp
-
- ; Set the baud rate for the current port, based on the value
- ; in the portinfo structure. Returns normally.
-
- BAUDST PROC NEAR
- mov dx,offset bdtab ; baud rate table, ascii
- xor bx,bx ; help is the table itself
- mov ah,cmkey ; get keyword
- call comnd
- jc baudst1 ; c = failure
- push bx ; save result
- mov ah,cmeol ; get confirmation
- call comnd
- pop bx
- jc baudst1 ; c = failure
- mov si,portval
- mov ax,[si].baud ; remember original value
- mov [si].baud,bx ; set the baud rate
- call dobaud ; use common code
- clc
- baudst1:ret
- BAUDST ENDP
-
- DOBAUD PROC NEAR
- push bx
- push ds
- pop es ; set es to data segment
- cld
- mov al,bl
- mov cl,4
- shl bl,cl ; shift constant into high nibble
- or al,bl
- out bdprt,al ; write into port
- or al,0f0h ; turn on high nibble
- push es
- mov bx,nvmseg
- mov es,bx
- mov es:[xmitbd],al
- mov es:[rcvbd],al ; set baud in nvm
- pop es
- pop bx
- ret
- DOBAUD ENDP
-
- ; Get the current baud rate from the serial card and set it
- ; in the portinfo structure for the current port. Returns normally.
- ; This is used during initialization.
-
- GETBAUD PROC NEAR
- push ax ; save some regs
- push bx
- push es
- mov ax,nvmseg
- mov es,ax
- mov al,es:[xmitbd] ; get xmit baud rate [gbs]
- pop es
- and ax,0fh ; only low nibble is used [gbs]
- mov bx,portval
- mov [bx].baud,ax ; set value
- pop bx ; restore regs
- pop ax
- ret ; and return
- GETBAUD ENDP
-
-
- ; Get Char from serial port buffer.
- ; skip returns if no character available at port,
- ; otherwise returns with char in al, # of chars in buffer in dx.
- ; Revised 22 May 1986, and again slightly 2 August 1986 by [jrd]
- ; Copied from msxibm.asm [jrd]
- PRTCHR PROC NEAR
- call chkxon ; see if we need to xon
- cmp repflg,0 ; REPLAY?
- je prtch0 ; e = no
- jmp prtch30 ; yes, do replay file reading
- prtch0: cmp count,0 ; any characters available?
- jnz prtch1 ; nz = yes, get one
- prtch0a:xor dx,dx ; return count of zero
- stc ; say no data
- ret
- prtch1: push si ; save si
- cli ; interrupts off, to keep srcpnt & count consistent
- mov si,srcpnt ; address of next available slot in buffer
- sub si,count ; minus number of unread chars in buffer
- cmp si,offset source ; located before start of buf?
- jae prtch2 ; ae = no
- add si,bufsiz ; else do arithmetic modulo bufsiz
- prtch2: mov al,byte ptr [si] ; get a character into al
- dec count ; one less unread char now
- sti ; interrupts back on now
- pop si
- mov dx,count ; return # of chars in buffer
- test flags.debug,logses ; debug mode?
- jnz prtch14 ; nz = yes, pass all chars
- cmp rxtable+256,0 ; translation turned off?
- jne prtch14 ; ne = table is on, pass all chars
- cmp al,0 ; NUL?
- je prtch13 ; e = yes, ignore it
- cmp al,DEL ; DEL char
- jne prtch14 ; ne = no, pass char
- prtch13:xor dx,dx
- stc ; no data
- ret
- prtch14:clc ; return char in al
- ret
-
- prtch30:push bx ; REPLAY, read char from a file
- push cx
- test xofsnt,usron ; user level xoff sent?
- jnz prtch31 ; nz = yes, suppress reading here
- xor dx,dx
- mov ax,100
- mov bx,1
- jmp $+2 ; flush lookahead buffer
- div bx ; burn some cpu cycles
- jmp $+2 ; because a 1 ms wait is too long
- div bx
- jmp $+2
- div bx
- mov ah,readf2
- mov bx,diskio.handle ; file handle
- mov cx,1 ; read one char
- mov dx,offset rdbuf ; to this buffer
- int dos
- jc prtch31 ; c = read failure
- cmp ax,cx ; read the byte?
- jne prtch31 ; ne = no
- pop cx
- pop bx
- mov al,rdbuf ; get the char into al
- mov dx,1 ; external char count
- clc
- ret ; return it
- prtch31:pop cx
- mov bx,portval
- mov [bx].portrdy,0 ; say port is not ready
- pop bx
- xor dx,dx
- stc ; say no char
- ret
- PRTCHR ENDP
-
-
- ; IHOSTS - Initialize the host by sending XON. Requires that the port be
- ; initialized.
- IHOSTS PROC NEAR
- push ax ; save the registers
- push cx
- push dx
- mov xofrcv,off ; clear old xoff received flag
- mov xofsnt,off ; and old xoff sent flag
- mov ah,flowon ; put Go-ahead flow control char in ah
- or ah,ah ; doing flow control?
- jz ihosts1 ; z = no, don't send a null
- call outchr ; send it (release Host's output queue)
- ihosts1:pop dx ; empty buffer. we are done here
- pop cx
- pop ax
- ret
- IHOSTS ENDP
-
- ; IHOSTR - initialize the remote host for our reception of a file by
- ; sending the flow-on character (XON typically) to release any held
- ; data. Called by receive-file code just after initializing the serial
- ; port. 22 March 1986 [jrd]
- ; Modified 26 June 1986 to supress sending a null if no flow control. [jrd]
- IHOSTR PROC NEAR
- push ax ; save regs
- push cx
- mov xofrcv,off ; clear old xoff received flag
- mov xofsnt,off ; and old xoff sent flag
- mov ah,flowon ; put Go-ahead flow control char in ah
- or ah,ah ; doing flow control?
- jz ihostr1 ; z = no, don't send a null
- call outchr ; send it (release Host's output queue)
- ihostr1:pop cx
- pop ax
- ret
- IHOSTR ENDP
-
- ; local routine to see if we have to transmit an xon
- chkxon proc near
- cmp flowon,0 ; doing flow control?
- je chkxo1 ; no, skip all this
- test xofsnt,usron ; did user send an xoff?
- jnz chkxo1 ; nz = yes, don't contradict it here
- test xofsnt,bufon ; have we sent a buffer level xoff?
- jz chkxo1 ; z = no, forget it
- cmp count,mntrgl ; below (low water mark) trigger?
- jae chkxo1 ; no, forget it
- mov ah,flowon ; ah gets xon
- and xofsnt,off ; remember we've sent the xon
- call outch2 ; send via non-flow controlled entry point
- chkxo1: ret
- chkxon endp
-
- ; Send a BREAK out the current serial port. Returns normally.
- SENDBR PROC NEAR
- push cx
- mov cx,275 ; 275 millisec
- call sendbw ; let worker routine do it
- pop cx
- clc ; don't exit Connect mode
- ret
- ; Send a Log BREAK out the current serial port.
- SENDBL: push cx
- mov cx,1800 ; 1800 millisec
- call sendbw ; let worker routine do it
- pop cx
- clc ; don't exit Connect mode
- ret
-
- sendbw: push ax ; worker routine to send a break [jrd]
- push bx ; number of millisec is in cx
- push dx
- mov ah,ioctl
- mov al,3 ; write to control channel
- mov bx,3 ; aux port handle
- mov dx,offset iobuf
- mov iobuf,stbrk ; start sending a break
- int dos
- mov ax,cx ; # of ms to wait
- call pcwait ; hold break for desired interval
- mov ah,ioctl
- mov al,3
- mov bx,3
- mov dx,offset iobuf
- mov iobuf,enbrk ; stop sending the break
- int dos
- pop dx
- pop bx
- pop ax
- clc
- ret
- SENDBR ENDP
-
-
- ; wait for the # of milliseconds in ax
- ; thanks to Bernie Eiben for this one.
- pcwait proc near
- push cx
- pcwai0: mov cx,240 ; inner loop counter for 1 millisecond
- pcwai1: sub cx,1 ; inner loop takes 20 clock cycles
- jnz pcwai1
- dec ax ; outer loop counter
- jnz pcwai0 ; wait another millisecond
- pop cx
- ret
- pcwait endp
-
-
- ; Position the cursor according to contents of DX:
- ; DH contains row, DL contains column. Returns normally.
-
- POSCUR PROC NEAR
- add dx,101H ; start at 1,1
- push es
- push ax ; save some regs
- push bx
- push di
- push dx
- cld
- mov ax,ds
- mov es,ax ; address data segment
- mov di,offset rowp
- mov al,dh ; row comes first
- mov ah,0
- call nout
- mov al,';'
- stosb ; separated by a semicolon
- pop dx
- mov al,dl
- mov ah,0
- call nout
- mov al,'H'
- stosb ; end w/H
- mov byte ptr [di],'$' ; and dollar sign
- mov dx,offset gopos
- call tmsg
- pop di ; restore regs
- pop bx
- pop ax
- pop es
- ret
- POSCUR ENDP
-
- ; Delete a character from the terminal. This works by printing
- ; backspaces and spaces. Returns normally.
-
- DODEL PROC NEAR
- mov dx,offset delstr ; Erase weird character
- jmp tmsg
- DODEL ENDP
-
- ; Move the cursor to the left margin, then clear to end of line.
- ; Returns normally.
-
- CTLU PROC NEAR
- mov dx,offset clrlin ; this just goes to left margin
- call tmsg
- jmp clearl ; now clear line
- CTLU ENDP
-
- ; set the current port.
-
- COMS PROC NEAR
- mov dx,offset nyimsg
- jmp tmsg
- COMS ENDP
-
- ; Set Terminal command
-
- VTS PROC NEAR ; SET TERM whatever [jrd]
- mov ah,cmkey ; parse key word
- xor bx,bx ; use built-in help
- mov dx,offset vttbl ; use this table
- call comnd
- jc vts0
- cmp bx,tttypes ; ROLL or more?
- ja vts4 ; a = yes
- ; SET TERM {VT52 | VT102}
- push bx
- mov ah,cmeol
- call comnd ; get a confirm
- pop bx
- jnc vts1 ; nc = success
- vts0: ret
- vts1: cmp bl,ttvt100 ; set to VT102?
- je vts2 ; e = yes
- mov flags.vtflg,ttvt52 ; say VT52
- jmp vts3
- vts2: mov flags.vtflg,ttvt100 ; say VT102
- vts3: call setterm ; send the message to the console
- ret
- vts4: mov ah,cmkey ; SET TERM ROLL
- mov bx,offset rolhlp ; help message
- mov dx,offset ontab ; table of answers
- call comnd
- jc vts6
- push bx
- mov ah,cmeol
- call comnd ; get a confirm
- pop bx
- jc vts6
- mov vtroll,bl ; set the flag
- vts6: ret
- VTS ENDP
-
- VTSTAT PROC NEAR ; Status routine for emulation. [jrd]
- mov bx,offset vtstbl ; table of things to show
- jmp statc ; status common code, in mssset
- VTSTAT ENDP
-
- ; initialization for using serial port. This routine performs
- ; any initialization necessary for using the serial port, including
- ; setting up interrupt routines, setting buffer pointers, etc.
- ; Doing this twice in a row should be harmless (this version checks
- ; a flag and returns if initialization has already been done).
- ; SERRST below should restore any interrupt vectors that this changes.
- ; Returns normally.
-
- SERINI PROC NEAR
- cmp portin,0 ; Did we initialize port already?
- jne serin0 ; ne = yes, so just leave
- cli ; Disable interrupts
- cld ; Do increments in string operations
- push es
- push si ; [ejz] - Save this just in case
- mov si,offset prtpar ; [ejz]
- mov dx,mnstata ; [ejz]
- push ds
- pop es ; set es to data segment
- call prtset ; [ejz]
- xor ax,ax ; Address low memory
- mov es,ax
- mov ax,es:[4*serchn] ; get old serial handler
- mov oldser,ax ; save
- mov ax,es:[4*serchn+2] ; get segment
- mov oldseg,ax ; save segment as well
- mov ax,es:[4*serch1] ; this is alternate for older rainbows
- mov old1ser,ax
- mov ax,es:[4*serch1+2]
- mov old1seg,ax ; pretty silly, huh?
- mov ax,offset serint ; point to our routine
- mov es:[4*serchn],ax ; point at our serial routine
- mov es:[4*serch1],ax ; have to set both of these
- mov es:[4*serchn+2],cs ; our segment
- mov es:[4*serch1+2],cs
- pop si ; [ejz]
- pop es
- mov al,0f1h ; enable RTS and DTR Note: bits reversed [gbs]
- out mnctrl,al ;[DTR] compared to documentation
- mov portin,1 ; Remember port has been initialized
- sti ; Allow interrupts
- push bx
- mov bx,portval ; get port
- mov parmsk,0ffh ; parity mask, assume parity is None
- cmp [bx].parflg,parnon ; is it None?
- je serin1 ; e = yes
- mov parmsk,07fh ; no, pass lower 7 bits as data
- serin1: mov bx,[bx].flowc ; get flow control chars
- mov flowoff,bl ; xoff or null
- mov flowon,bh ; xon or null
- pop bx
- serin0: clc ; carry clear for success
- ret
- SERINI ENDP
-
- ; this is used to by serini
- prtset proc near
- cld
- lodsb ; get a byte
- or al,al
- jz prtse1 ; end of table, stop here
- out dx,al ; else send it out
- jmp short prtset ; and keep looping
- prtse1: ret ; end of routine
- prtset endp
-
- ; Reset the serial port. This is the opposite of serini. Calling
- ; this twice without intervening calls to serini should be harmless.
- ; Returns normally.
-
- SERRST PROC NEAR
- cmp portin,0 ; reset already?
- je srst1 ; e = yes, just leave
- cli ; disable interrupts
- push es ; preserve this
- xor ax,ax
- mov es,ax ; address segment 0
- mov ax,oldser
- mov es:[4*serchn],ax
- mov ax,oldseg
- mov es:[4*serchn+2],ax
- mov ax,old1ser
- mov es:[4*serch1],ax
- mov ax,old1seg
- mov es:[4*serch1+2],ax ; restore old handlers
- mov portin,0 ; reset flag
- pop es
- sti ; re-enable interrupts
- srst1: ret
- SERRST ENDP
-
- ; serial port interrupt routine. This is not accessible outside this
- ; module, handles serial port receiver interrupts.
- ; New code, lifted from msxibm. [jrd]
- serint PROC NEAR
- push ax
- push ds
- push bx
- push dx
- mov ax,seg data
- mov ds,ax ; address data segment
- mov dx,mnstatb ; Asynch status port
- xor al,al ; innocuous value
- out dx,al ; send out to get into a known state
- mov al,2 ; now address register 2
- out dx,al
- in al,dx ; read interrupt cause
- cmp al,7 ; in range?
- ja serin7 ; no, just dismiss (what about reset error?)
- mov bl,al
- shl bl,1 ; double for word index
- xor bh,bh
- call ivec[bx] ; call appropriate handler
- jmp short serin8
- serin7: mov dx,mnstata ; reload port address
- mov al,38H
- out dx,al ; tell the port we finished with the interrupt
- sti ; turn on interrupts
- serin8: pop dx
- pop bx
- pop ds
- pop ax
- intret: iret
-
- ; handler for serial receive, port A
-
- srcva: mov dx,mnstata
- xor al,al ; Asynch status port
- out dx,al ; put into known state
- jmp $+2
- in al,dx
- test al,rxrdy ; Data available?
- jnz srcva0a ; nz = yes
- srcva0: mov dx,mnstata
- mov al,38h ; tell port we are finished with the interrupt
- out dx,al
- sti ; turn on interrupts
- jmp retint ; and exit now (common jump point)
-
- srcva0a:;;and al,mdmover ; select overrun bit
- ;; mov overrun,al ; save it for later
- mov al,30h ; clear any errors
- out dx,al
- mov dx,mndata ; get modem rx data
- in al,dx ; read the received character into al
- cmp flowoff,0 ; flow control active?
- je srcva2 ; e = no
- mov ah,al ; ah = working copy. Check null, flow cntl
- and ah,parmsk ; strip parity temporarily, if any
- cmp ah,flowoff ; acting on Xoff?
- jne srcva1 ; ne = Nope, go on
- mov xofrcv,bufon ; Set the flag saying XOFF received
- jmp srcva0 ; and exit
- srcva1: cmp ah,flowon ; acting on Xon?
- jne srcva2 ; ne = no, go on
- mov xofrcv,off ; Clear the XOFF received flag
- jmp srcva0 ; and exit
- srcva2: push ax ; save rcvd char around this output cmd
- mov dx,mnstata
- mov al,38h ; tell port we are finished with the interrupt
- out dx,al
- pop ax
- cli ; ensure interrupts are off, critical section
- ;; mov ah,overrun ; get overrun flag
- ;; or ah,ah ; overrun?
- ;; jz srcva2a ; z = no
- ;; mov ah,al ; yes, save present char
- ;; mov al,bell ; insert control-G for missing character
- srcva2a:mov bx,srcpnt ; address of buffer storage slot
- mov byte ptr [bx],al ; store the new char in buffer "source"
- inc srcpnt ; point to next slot
- inc bx
- cmp bx,offset source + bufsiz ; beyond end of buffer?
- jb srcva3 ; b = not past end
- mov srcpnt,offset source ; wrap buffer around
- srcva3: cmp count,bufsiz ; filled already?
- jae srcva4 ; ae = yes
- inc count ; no, add a char
- srcva4:;;or ah,ah ; anything in overrun storage?
- ;; jz srcva4a ; z = no
- ;; mov al,ah ; recover any recent char from overrun
- ;; xor ah,ah ; clear overrun storage
- ;; jmp srcva2a ; yes, go store real second char
- srcva4a:sti ; ok to allow interrupts now, not before
- cmp count,mntrgh ; past the high trigger point?
- jbe retint ; be = no, we're within our limit
- test xofsnt,bufon ; Has an XOFF been sent by buffer control?
- jnz retint ; nz = yes
- mov al,flowoff ; get the flow off char (Xoff or null)
- or al,al ; don't send null chars
- jz retint ; z = null, nothing to send
- call dopar ; Set parity appropriately
- mov ah,al ; Don't overwrite character with status
- push cx ; save reg
- xor cx,cx ; loop counter
- srcva5: mov dx,mnstata ; port status register
- in al,dx
- test al,txrdy ; Transmitter ready?
- jnz srcva6 ; nz = yes
- push ax ; use time, prevent overdriving UART
- pop ax
- loop srcva5 ; else wait loop, cx times
- jmp short srcva7 ; Timeout
- srcva6: mov al,ah ; Now send out the flow control char
- mov dx,mndata
- out dx,al
- mov xofsnt,bufon ; Remember we sent an XOFF at buffer level
- srcva7: pop cx ; restore reg
- retint: ret
-
- ; The interrupt is for the 'B' port - transfer control to
- ; the original handler and hope for the best.
- tranb: pushf ; put flags on stack to simulate interrupt
- call dword ptr [old1ser] ; call old handler
- jmp srccom ; take common exit
-
- stxa: mov dx,mnstata
- mov al,28H ; reset transmit interrupt
- out dx,al
- jmp srccom ; take common exit
-
- sstata: mov dx,mnstata
- mov al,10H ; reset status interrupt
- out dx,al ; fall through to common exit srccom below
-
- srccom: mov dx,mnstata ; common exit for above
- mov al,38h ; tell port we are finished with the interrupt
- out dx,al
- sti ; turn on interrupts
- ret
-
- SERINT ENDP
-
- DTRLOW PROC NEAR ; Global proc to Hangup the Phone by making
- ; DTR and RTS low.
- mov ah,cmline ; allow text, to display help
- mov bx,offset rdbuf ; dummy buffer
- mov dx,offset hnghlp ; help message
- call comnd ; get a confirm
- jc dtrlow1
- call serhng ; drop DTR and RTS
- mov ah,prstr ; give a nice message
- mov dx,offset hngmsg
- int dos
- clc
- dtrlow1:ret
- DTRLOW ENDP
-
- ; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
- ; to terminate the connection. 29 March 1986 [jrd]
- ; Calling this twice without intervening calls to serini should be harmless.
- ; Returns normally.
-
- serhng proc near
- call serrst ; reset the port so can be restarted cleanly
- cli ; Disable interrupts
- mov al,0ffh ; disable RTS and DTR [gbs]
- out mnctrl,al ; [DTR]
- sti ; Allow interrupts
- mov ax,500
- call pcwait ; wait 500ms
- clc
- ret
- serhng endp
-
- ; Produce a short beep.
- ; Returns normally.
-
- BEEP PROC NEAR
- mov dl,bell
- mov ah,conout
- int dos
- clc
- ret
- BEEP ENDP
-
- ; put the number in ax into the buffer pointed to by di. Di is updated
- nout proc near
- mov dx,0 ; high order is always 0
- mov bx,10
- div bx ; divide to get digit
- push dx ; save remainder digit
- or ax,ax ; test quotient
- jz nout1 ; zero, no more of number
- call nout ; else call for rest of number
- nout1: pop ax ; get digit back
- add al,'0' ; make printable
- cld
- stosb ; drop it off
- ret
- nout endp
-
-
- term proc near
- mov si,ax ; this is source
- mov argadr,ax ; save here too
- mov di,offset ourarg ; place to store arguments
- mov ax,ds
- mov es,ax ; address destination segment
- mov cx,size termarg
- cld
- rep movsb ; copy into our arg blk
- cmp inited,0 ; inited yet?
- jne term0 ; ne = yes
- call cmblnk ; clear the screen
- call locate ; put cursor at top left corner
- mov inited,1 ; say initialized
- jmp short term0a
- term0: call rstscr ; restore screen
- term0a: mov inited,1 ; remember inited
- mov parmsk,0ffh ; parity mask, assume parity = None
- cmp ourarg.parity,parnon ; is parity None?
- je term1 ; e = yes, keep all 8 bits
- mov parmsk,07fh ; else keep lower 7 bits
-
- term1: call portchr ; get char from port, apply parity mask
- jnc short term3 ; nc = char
- term2: mov fairness,0 ; say kbd was examined
- call keybd ; call keyboard translator in msu
- jnc term1 ; nc = no char or have processed it
- call pntflsh ; flush printer buffer
- call savscr ; save screen
- mov dx,offset gtobot ; go to last line on screen
- call tmsg
- stc
- ret ; carry set = quit connect mode
-
- term3: call outtty ; print on terminal
- inc fairness ; say read port but not kbd, again
- cmp fairness,200 ; this many port reads before kbd?
- jb term1 ; b = no, read port again
- call pntflsh ; flush printer buffer
- jmp short term2 ; yes, let user have a chance too
- term endp
-
- ; Get a char from the serial port manager, return it in al
- ; returns with carry clear if a character is available, else carry set
- portchr proc near
- call prtchr ; character at port?
- jnc portc1 ; nc = yes
- portc0: stc ; carry = no character
- ret
- portc1: and al,parmsk ; apply 8/7 bit parity mask
- or al,al ; catch nulls
- jz portc0 ; z = null, ignore it
- cmp al,del ; catch dels
- je portc0 ; e = del, ignore it
- portc2: clc ; have a character, in AL
- ret
- portchr endp
-
- ; put the character in al to the screen
- outtty proc near
- push es ; protect es around fastcon calls
- test flags.remflg,d8bit ; keep 8 bits for displays?
- jnz outnp5 ; nz = yes, 8 bits if possible
- and al,7fh ; remove high bit
- outnp5: cmp rxtable+256,0 ; translation turned off?
- je outnp7 ; e = yes, no translation
- push bx
- mov bx,offset rxtable ; address of translate table
- xlatb ; new char is in al
- pop bx
- outnp7: test ourflgs,fpscr+vtautop+vtcntp ; should we be printing?
- jz outnop ; z = no, keep going
- call pntchr ; queue char for printer
- jnc outnop ; nc = successful print
- push ax
- call beep ; else make a noise and
- call trnprs ; turn off printing
- pop ax
- and ourflgs,not (fpscr+vtautop+vtcntp) ; turn off printing
- pop ax
- outnop: test ourarg.flgs,capt ; capturing output?
- jz outnoc ; z = no, forget this part
- push ax ; save char
- call ourarg.captr ; give it captured character
- pop ax ; restore character and keep going
- outnoc:
- cmp vtroll,0 ; auto roll back allowed?
- jz outnp6 ; z = no, leave screen as is
- cmp bwnd.lcnt,0 ; is screen rolled back? [dlk]
- je outnp6 ; e = no
- call nxtbot ; restore screen before writing [dlk]
- outnp6: push ax
- call scrprep ; need to save top line
- pop ax
- test ourarg.flgs,trnctl ; debug? if so use Bios tty mode
- jz outnp3 ; z = no
- cmp al,7fh ; Ascii Del char or greater?
- jb outnp1 ; b = no
- je outnp0 ; e = Del char
- push ax ; save the char
- mov al,7eh ; output a tilde for 8th bit
- int fastcon
- pop ax ; restore char
- and al,7fh ; strip high bit
- outnp0: cmp al,7fh ; is char now a DEL?
- jne outnp1 ; ne = no
- and al,3fH ; strip next highest bit (Del --> '?')
- jmp outnp2 ; send, preceded by caret
- outnp1: cmp al,' ' ; control char?
- jae outnp3 ; ae = no
- add al,'A'-1 ; make visible
- outnp2: push ax ; save char
- mov al,5eh ; caret
- int fastcon ; display it
- pop ax ; recover the non-printable char
- outnp3: call ansbak ; match answerback sequences
- test ourflgs,vtcntp ; autoprint on? ;gbs
- jnz outnp4 ; if so, don't output to screen
- push ax
- int fastcon ; write without intervention
- pop ax
- outnp4: pop es
- ret
- outtty endp
-
- ; enter with current terminal character in al.
- ; calls answerback routine if necessary.
- ; This can be used to make the emulator recognize any sequence.
- ansbak proc near
- push bx
- mov bx,offset ansbk1 ; check 1st answerback
- call ansbak0 ; check for answerback
- mov bx,offset ansbk2 ; maybe second answerback
- call ansbak0 ; should probably loop thru a table
- mov bx,offset ansbk3
- call ansbak0
- mov bx,offset ansbk4
- call ansbak0
- mov bx,offset ansbk5
- call ansbak0
- mov bx,offset ansbk6
- call ansbak0
- mov bx,offset ansbk7
- call ansbak0
- mov bx,offset ansbk8
- call ansbak0
- mov bx,offset ansbk9
- call ansbak0
- mov bx,offset ansbk10
- call ansbak0
- mov bx,offset ansbk11
- call ansbak0
- mov bx,offset ansbk12
- call ansbak0
- mov bx,offset ansbk13
- call ansbak0
- mov bx,offset ansbk14
- call ansbak0
- pop bx
- ret
- ansbak0: ; worker routine for above
- push ax ; preserve these
- push si
- mov si,[bx].anspt ; get current pointer
- cmp al,[si] ; is it correct?
- jne ansba1 ; no, reset pointers and go on
- inc [bx].anspt ; increment pointer
- dec [bx].ansct ; decrement counter
- jnz ansba2 ; not done, go on
- push bx
- call [bx].ansrtn ; send answerback
- pop bx
- ansba1: mov ax,[bx].ansseq ; get original sequence
- mov [bx].anspt,ax
- mov al,[bx].anslen ; and length
- mov [bx].ansct,al
- ansba2: pop si
- pop ax
- ret
- ansbak endp
-
- ; send the answerback message.
- sndans proc near
- push cx
- mov si,offset ansret ; ansi ident message
- mov cx,ansrln ; length of same
- push es ; save seg register
- mov ax,nvmseg ; fetch address of nvm
- mov es,ax ; put in segment reg
- test byte ptr es:[vt52mod],1 ; check bit zero
- pop es ; restore the seg register
- jnz sndan1 ; nz = ansi mode
- mov si,offset VT52ret ; say VT52
- mov cx,VT52ln
- sndan1: cld
- lodsb ; get a byte
- mov ah,al
- push si
- push cx
- call outchr ; send ah out the serial port
- pop cx
- pop si
- loop sndan1
- pop cx
- ret
- sndans endp
-
- ; enable alternate keypad mode
- enaaky proc near
- mov akeyflg,1 ; set keypad alternate mode
- ret
- enaaky endp
-
- ; disable alternate keypad mode
- deaaky proc near
- mov akeyflg,0
- ret
- deaaky endp
-
- cuapp proc near
- mov ckeyflg,1 ; set cursor keys to applications mode
- ret
- cuapp endp
-
- cunapp proc near
- mov ckeyflg,0 ; set cursor keys to cursor mode
- ret
- cunapp endp
-
- ; ESC c handler.
- ; Send a space so the firmware doesn't see bad escape sequences. [jrd]
- sndspc proc near
- mov akeyflg,0 ; reset keypad applications mode
- mov ckeyflg,0 ; reset cursor applications mode
- mov al,' ' ; space separates the ESC and 'c'
- int fastcon ; send this to upset esc parser
- push ax
- call nxtbot ; go to end of screen buffer
- call cmblnk ; clear the screen too
- pop ax
- clc
- ret
- sndspc endp
-
- ; answer a cursor position report
- ansenq proc near
- push es
- push di
- mov di,offset rdbuf ; convenient scratch buffer
- mov al,escape
- cld
- push ds
- pop es ; set es to data segment
- stosb
- mov al,'['
- stosb
- push es
- mov ax,scrseg
- mov es,ax
- mov al,es:[csrlin]
- mov ah,es:[csrcol]
- pop es
- push ax
- xor ah,ah
- call nout
- mov al,';'
- stosb
- pop ax
- xchg ah,al
- xor ah,ah
- call nout
- mov al,'R'
- stosb
- mov si,offset rdbuf
- sub di,si
- mov cx,di
- ansen1: lodsb ; get a byte
- push si
- push cx
- mov ah,al
- call outchr ; send it along
- pop cx
- pop si
- loop ansen1 ; loop thru all
- pop di
- pop es
- ret ; and return
- ansenq endp
-
- ; set terminal to vt52 or vt102, based on current flags.vtflg [jrd]
- setterm proc near
- push es ; save seg register
- mov ax,nvmseg ; fetch address of nvm
- mov es,ax ; put in segment reg
- test byte ptr es:[vt52mod],1 ; check bit zero
- pop es ; restore the seg register
- push ds
- pop es ; set es to data segment
- cld
- jnz setter1 ; nz = ansi mode
- cmp flags.vtflg,ttvt52 ; are we already a VT52?
- je setterx ; e = nothing to do
- mov si,offset dovt102 ; change from vt52 to VT102
- jmp setter2
- setter1:cmp flags.vtflg,ttvt100 ; already a VT102?
- je setterx ; e = nothing to do
- mov si,offset dovt52 ; change from vt102 to vt52
- setter2:lodsb
- cmp al,'$'
- je setterx
- push es
- push si
- int fastcon
- pop si
- pop es
- jmp setter2
- setterx:ret
- setterm endp
-
- ; Handle the print screen key - copy whole screen to printer.
- ; Rewritten 26 June 1986 by [jrd] to avoid confusion over segment addressing
- ; and line length counting. Based on procedure dumpscr code.
- ; 30-Apr-1990 [gbs] convert line-drawing characters to ".". Otherwise, they
- ; output as control characters. (Could shift in/shift out if output
- ; printer is DEC printer.)
- ; 24-AUG-1990 [rhw-3] added translation table for VT100 graphics to chars
- ; a normal printer (even non-dec) can swollow. At least linedraw will
- ; come out looking like boxes, etc. See xlat_tab usage below...
- ; This replaces [gbs] change above.
- ;
- prtscn proc near
- push ax ; save some regs
- push bx
- push cx
- push dx
- push si
- push di
- push es
- call pntflsh ; flush printer buffer now
- xor bx,bx ; index for current line pointer
- mov cx,slen ; number of screen lines
- prtsc1: push cx ; save outer loop (lines to do) count
- push bx ; save index value for bottom of loop
- mov cx,swidth ; number of screen columns = 132
- mov di,offset dumpbuf ; data segment memory (work buffer)
- mov ax,scrseg ; make es hold screen segment
- mov es,ax ; for inner read-a-row loop
- mov si,es:[latofs+bx] ; get pointer to current line
- and si,0fffh ; only 12 bits are significant
- prtsc2: mov al,es:byte ptr [si] ; inner loop. read text char
- mov byte ptr [di],al ; just store char, don't use es:
- inc si ; update pointers (si needed below)
- inc di
- loop prtsc2 ; do for all 132 columns, fixed format
- ; find end of line, replace nulls with spaces
- mov cx,swidth ; max chars in a line
- mov di,offset dumpbuf ; look at start of line
- prtsc3: mov al,byte ptr [di] ; get a byte into al
- cmp al,0ffh ; end of line indicator?
- je prtsc5 ; e = yes, exit with count left in cx
- ;; cmp al,0 ; is it a nasty null? x[rhw-3]
- ;; jne prtsc4 ; ne = no x[rhw-3]
- ;; mov al,' ' ; replace null with nice space x[rhw-3]
-
- prtsc4: cmp al,' ' ; is it a ctrl (line-draw) char? [gbs]
- jae prtsc4a ; ae = no
- ;; mov al,'.' ; if so, replace with "."[gbs], x[rhw-3]
- mov dx,bx ; [rhw-3] save bx, need to use it
- mov bx,offset xlat_tab ; [rhw-3] get ptr to xlation buffer
- xlat ; [rhw-3] lookup & swap old for new char
- mov bx,dx ; [rhw-3] restore bx
-
- prtsc4a:mov byte ptr [di],al ; put back into buffer
- inc di ; look ahead for next char
- loop prtsc3 ; scan the rest of the line
- prtsc5: dec di ; make di point at eol address
- mov ax,swidth ; max line length
- sub ax,cx ; minus chars scanned = length of line
- mov cx,ax ; remember it here
- ; trim line of trailing spaces
- mov ax,ds ; di needs to point to data space
- mov es,ax ; string ops use es:di
- mov al,' ' ; thing to scan over
- std ; set scan backward
- repe scasb ; scan until non-space, dec's di
- cld ; set direction forward
- jz prtsc6 ; z = all spaces (count was exhausted)
- inc cx ; go forward over last non-space
- inc di ; ditto for address
- prtsc6: mov word ptr [di+1],0A0Dh ; append cr/lf
- add cx,2 ; line count + cr/lf
- mov dx,offset dumpbuf ; array to be written
- mov bx,prnhand ; file handle of Connect mode printer
- mov ah,write2 ; write the line
- int dos
- pop bx ; restore index for line pointer
- inc bx ; add 2 for next pointer's location
- inc bx
- pop cx ; get line counter again
- loop prtsc1 ; do next line (needs si preset)
- pop es
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- clc
- ret
- prtscn endp
-
- ; toggle print flag. If turning on printing, check for printer ready; skip
- ; printing if not ready and beep the user. [jrd]
- trnprs proc near
- test ourflgs,fpscr ; printing currently?
- jnz trnpr1 ; nz = yes, its on and going off
- call ckprn ; see if printer is available
- jc trnpr2 ; c = printer not ready
- trnpr1: xor ourflgs,fpscr ; flip the flag
- trnpr2: clc
- ret
- trnprs endp
-
- ; autoprint on
- apon proc near
- call ckprn ; printer ready?
- jc apon1 ; c = printer not ready
- or ourflgs,vtautop ; enable autoprint
- apon1: clc
- ret
- apon endp
-
- ; autoprint off
- apoff proc near
- and ourflgs,not vtautop ; disable autoprint
- ret
- apoff endp
-
- ; print controller on
- prconon proc near
- call ckprn ; printer ready?
- jc pcon1 ; c = printer not ready
- or ourflgs,vtcntp ; enable print controller
- pcon1: clc
- ret
- prconon endp
-
- ; print controller off
- pconoff proc near
- and ourflgs,not vtcntp ; disable print controller
- ret
- pconoff endp
-
- ; check for printer ready -
- ; if not ready, return carry and beep
- ckprn proc near
- push ax
- mov ah,ioctl
- mov al,7 ; get output status of printer
- push bx
- mov bx,prnhand ; file handle for system printer
- int dos
- pop bx
- jc ckprn1 ; not ready...return carry
- cmp al,0ffh ; Ready status?
- jnz ckprn1 ; nz ==> not ready
- clc ; show ready
- jmp ckprn2
- ckprn1: call beep ; let someone know
- stc ; indicate not ready
- ckprn2: pop ax
- ret
- ckprn endp
-
-
- ; Save the screen to a buffer and then append buffer to a disk file. [jrd]
- ; Default filename is Kermit.scn; actual file can be a device too. Filename
- ; is determined by mssset and is passed as pointer dmpname.
- ; Modified 1 Sept 1986 to do test for dump destination being ready. [jrd]
- ; Modified 24-AUG-90 [rhw-3] added translation table for VT100 graphics
- ; to normal ascii chars. This will make the dump file readable &
- ; printable on any printer (even non-dec). Now linedraw chars will
- ; come out looking like boxes, etc. See xlat_tab usage below...
-
- dumpscr proc near ; global dump-screen procedure
- push ax
- push bx
- push cx
- push dx
- call savscr ; first, save screen to memory
- mov dmphand,-1 ; preset illegal handle
- mov dx,offset dmpname ; name of disk file, from mssset
- mov ax,dx ; where isfile wants name ptr
- call isfile ; what kind of file is this?
- jc dmp5 ; c = no such file, create it
- test byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
- jnz dmp0 ; nz = no.
- mov al,1 ; writing
- mov ah,open2 ; open existing file
- int dos
- jc dmp0 ; c = failure
- mov dmphand,ax ; save file handle
- mov bx,ax ; need handle here
- mov cx,0ffffh ; setup file pointer
- mov dx,-1 ; and offset
- mov al,2 ; move to eof minus one byte
- mov ah,lseek ; seek the end
- int dos
- jmp dmp1
-
- dmp5: test filtst.fstat,80h ; access problem?
- jnz dmp0 ; nz = yes
- mov ah,creat2 ; file did not exist
- mov cx,20h ; attributes, archive bit
- int dos
- mov dmphand,ax ; save file handle
- jnc dmp1 ; nc = ok
-
- dmp0: mov dx,offset dmperr ; say no can do
- mov ah,prstr
- int dos
- pop dx
- pop cx
- pop bx
- pop ax
- clc
- ret
- ; read screen buffer (132 char/line), write lines to file
- dmp1: mov ah,ioctl ; is destination ready for output?
- mov al,7 ; test output status
- mov bx,dmphand ; handle
- int dos
- jc dmp0 ; c = error
- cmp al,0ffh ; ready?
- jne dmp0 ; ne = not ready
- push di ; save regs around this work
- push si
- mov si,ourscr ; buffer where screen was stored
- mov cx,slen ; number of saved screen lines
- dmp2: push cx ; save outer loop counter
- mov di,offset dumpbuf ; data segement memory (work buffer)
- mov cx,swidth ; number of screen columns = 132
- dmp3: mov al,byte ptr [si] ; read text char
- mov byte ptr [di],al ; store just char, don't use es:
- inc si ; update pointers (si needed below)
- inc di
- loop dmp3 ; do for all 132 columns, fixed format
- ; find end of line, replace nulls with spaces
- mov cx,swidth ; max chars in a line
- mov di,offset dumpbuf ; look at start of line
- dmp7: mov al,byte ptr [di] ; get a byte into al
- cmp al,0ffh ; end of line indicator?
- je dmp9 ; e = yes, exit with count left in cx
-
- ;; cmp al,0 ; is it a nasty null? x[rhw-3]
- ;; jne dmp8 ; ne = no x[rhw-3]
- ;; mov al,' ' ; replace null with nice space x[rhw-3]
- cmp al,' ' ; [rhw-3] see if unprintable
- jae dmp8 ; [rhw-3] if its >= space then ok
- mov dx,bx ; [rhw-3] save bx, need to use it
- mov bx,offset xlat_tab ; [rhw-3] get ptr to xlation buffer
- xlat ; [rhw-3] lookup & swap old for new char
- mov bx,dx ; [rhw-3] restore bx
-
- dmp8: mov byte ptr [di],al ; put back into buffer
- inc di ; look ahead for next char
- loop dmp7 ; scan the rest of the line
- dmp9: dec di ; make di point at eol address
- mov ax,swidth ; max line length
- sub ax,cx ; minus chars scanned = length of line
- mov cx,ax ; remember it here
- ; trim line of trailing spaces
- push es ; save register
- mov ax,ds ; di needs to point to data space
- mov es,ax ; string ops use es:di
- mov al,' ' ; thing to scan over
- std ; set scan backward
- repe scasb ; scan until non-space, dec's di
- cld ; set direction forward
- pop es ; restore reg
- jz dmp3a ; z = all spaces (count was exhausted)
- inc cx ; go forward over last non-space
- inc di ; ditto for address
- dmp3a: mov word ptr [di+1],0A0Dh ; append cr/lf
- add cx,2 ; line count + cr/lf
- mov dx,offset dumpbuf ; array to be written
- mov bx,dmphand ; need file handle
- mov ah,write2 ; write the line
- int dos
- pop cx ; get line counter again
- loop dmp2 ; do next line (needs si preset)
- mov dx,offset dumpsep ; put in formfeed/cr/lf
- mov cx,3 ; three bytes overall
- mov ah,write2
- mov bx,dmphand
- int dos
- mov ah,close2 ; close the file now
- int dos
- pop si
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- clc
- ret
- dumpscr endp
-
- ; Send a character to the host, handle local echo
- sndhst proc near
- push ax ; save the character
- mov ah,al
- call outchr ; send char in ah out the serial port
- pop ax
- test ourarg.flgs,lclecho ; echoing?
- jz sndhs2 ; z = no, exit
- call outtty ; echo to screen
- sndhs2: ret
- sndhst endp
-
-
- ; print a message to the screen. Returns normally.
- ; also puts the terminal into vt100 mode so our escape sequences work...
- tmsg proc near
- push es
- push bx
- mov bx,nvmseg
- mov es,bx ; address firmware
- mov bl,0f1h ; turn on vt100 mode
- xchg bl,es:[vt52mod] ; remember old mode
- mov ah,prstr
- int dos
- mov es:[vt52mod],bl ; restore mode
- pop bx
- pop es
- ret
- tmsg endp
-
- ; save the screen for later
- savscr proc near
- push es
- push ds
- call kilcur ; turn off cursor
- mov di,ourscr ; place to save screen
- mov dx,ourattr ; and to save attributes
- mov ax,ds
- mov es,ax ; save buffer is in data space (ds seg)
- mov cx,slen ; # of lines to do
- mov ax,scrseg
- mov ds,ax
- mov bx,0 ; current line #
- savsc1: push cx ; save current count
- mov si,ds:[latofs+bx] ; get line ptr
- and si,0fffh ; ptr is in 12 bits
- push si ; save pointer
- mov cx,swidth/2 ; # of words/line, [RHW-5] swidth always even
- cld
- rep movsw ; [RHW-4] copy it out by words
- pop si ; restore pointer
- add si,attoffs ; this is where attributes start
- xchg dx,di ; this holds attribute ptr
- mov cx,swidth/2 ; # of words of attrs to move, [RHW-5]
- rep movsw ; [RHW-4] copy words at a time (quicker)
- xchg dx,di
- pop cx ; restore counter
- add bx,2 ; increment line ptr
- loop savsc1 ; save all lines and attributes
- pop ds
- call rstcur ; put cursor back
- call savpos ; might as well save cursor pos
- pop es
- ret
- savscr endp
-
- ; restore the screen saved by savscr
- rstscr proc near
- call cmblnk ; start by clearing screen
- mov si,ourscr ; point to saved screen
- mov dx,ourattr ; and attributes
- mov cx,slen ; # of lines/screen
- mov bx,101H ; start at top left corner
- rstsc1: push bx
- push cx
- push si ; save ptrs
- push dx
- mov ax,si ; this is source
- call prlina ; print the line
- pop dx
- pop si
- pop cx
- pop bx
- add si,swidth ; point to next line
- add dx,swidth ; and next attributes
- inc bx ; address next line
- loop rstsc1 ; keep restore lines
- call rstpos ; don't forget position
- ret
- rstscr endp
-
- ; Put a line into the circular buffer. Pass the buffer structure in bx.
- ; Source is srcseg:si
- ; Rewritten by [jrd]
- putcirc proc near
- push es
- push di
- push cx
- mov cl,swidth ; number of columns
- xor ch,ch
- mov es,[bx].orig ; get segment of memory area
- cmp bx,offset bwnd ; bottom buffer?
- je putci6 ; e = yes
- mov di,twnd.pp ; pick up buffer ptr (offset from es)
- add di,cx ; increment to next available slot
- add di,cx ; char and attribute
- cmp di,twnd.bend ; would line extend beyond buffer?
- jb putci1 ; b = not beyond end
- mov di,0 ; else start at the beginning
- putci1: mov twnd.pp,di ; update ptr
- cld ; set direction to forward
- mov cx,swidth
- push ds ; save regular data seg reg
- mov ds,srcseg ; use source segment for ds:si
- rep movsw ; copy into buffer
- pop ds ; restore regular data segment
- mov cx,twnd.lmax ; line capacity of buffer
- dec cx ; minus one work space line
- cmp twnd.lcnt,cx ; can we increment line count?
- jae putci1b ; ae = no, keep going
- inc twnd.lcnt ; else count this line
- putci1b:cmp bwnd.lcnt,0 ; any lines in bottom buffer?
- je putci2 ; e = no
- mov cx,bwnd.pp ; see if we overlap bot buf
- cmp cx,twnd.pp ; is this line in bot buf area?
- jne putci2 ; ne = no
- add cl,swidth ; move bottom pointer one slot earlier
- adc ch,0
- add cl,swidth ; words
- adc ch,0
- cmp cx,bwnd.bend ; beyond end of buffer?
- jb putci1a ; b = no
- mov cx,0 ; yes, start at beginning of buffer
- putci1a:mov bwnd.pp,cx ; new bottom pointer
- dec bwnd.lcnt ; one less line in bottom buffer
- putci2: pop cx
- pop di
- pop es
- ret
- putci6: ; bottom buffer
- add cx,cx ; words worth
- cmp bwnd.lcnt,0 ; any lines in the buffer yet?
- jne putci7 ; ne = yes
- mov di,twnd.pp ; get latest used slot of top buff
- add di,cx ; where first free (?) slot starts
- cmp di,bwnd.bend ; are we now beyond the buffer?
- jb putci6a ; b = no
- mov di,0 ; yes, start at beginning of buffer
- putci6a:add di,cx ; start of second free (?) slot
- cmp di,bwnd.bend ; are we now beyond the buffer?
- jb putci6b ; b = no
- mov di,0 ; yes, start at beginning of buffer
- putci6b:mov cx,twnd.lmax ; buffer line capacity
- sub cx,twnd.lcnt ; minus number used by top buffer
- sub cx,2 ; minus one work slot and one we need
- cmp cx,0 ; overused some slots?
- jge putci8 ; ge = enough to share
- add twnd.lcnt,cx ; steal these from top window beginning
- jmp short putci8
-
- putci7: mov es,bwnd.orig ; get segment of memory area
- mov di,bwnd.pp ; pick up buffer ptr (offset from es)
- cmp di,0 ; would line start before buffer?
- jne putci7a ; ne = after start of buffer
- mov di,bwnd.bend ; else start at the end minus one slot
- inc di
- putci7a:sub di,cx
- putci8: mov bwnd.pp,di ; update ptr (this is latest used slot)
- mov cl,swidth
- xor ch,ch
- cld ; set direction to forward
- push ds ; save regular data seg reg
- mov ds,srcseg ; use source segment for ds:si
- rep movsw ; copy into buffer
- pop ds ; restore regular data segment
- mov cx,bwnd.lmax ; line capacity of buffer
- cmp bwnd.lcnt,cx ; can we increment line count?
- jae putci8b ; ae = no, keep going
- inc bwnd.lcnt ; else count this line
- putci8b:cmp twnd.lcnt,0 ; any lines in top line buf?
- je putci9 ; e = no
- mov cx,twnd.pp ; yes, see if we used last top line
- cmp cx,bwnd.pp ; where we just wrote
- jne putci9 ; not same place, so all is well
- dec twnd.lcnt ; one less line in top window
- cmp cx,0 ; currently at start of buffer?
- jne putci8a ; ne = no
- mov cx,twnd.bend ; yes
- inc cx
- putci8a:sub cl,swidth ; back up top window
- sbb ch,0
- sub cl,swidth ; by one line
- sbb ch,0
- mov twnd.pp,cx ; next place to read
- putci9: pop cx
- pop di
- pop es
- ret
-
- putcirc endp
-
- ; Get a line from the circular buffer, removing it from the buffer.
- ; returns with carry on if the buffer is empty.
- ; Pass the buffer structure in bx.
- ; Destination preset in es:di.
- ; Rewritten by [jrd]
- getcirc proc near
- cmp [bx].lcnt,0 ; any lines in buffer?
- jne getci1 ; ne = yes, ok to take one out
- stc ; else set carry
- ret ; and return
- getci1: push cx ; top and bottom window common code
- push si
- mov cl,swidth ; # of chars to copy
- xor ch,ch
- push di ; save destintion offset
- push cx ; save around calls
- mov si,[bx].pp ; this is source
- cld ; set direction to forward
- push ds ; save original ds
- mov ds,[bx].orig ; use seg address of buffer for si
- rep movsw
- pop ds ; recover original data segment
- pop cx ;
- pop di ; recover destination offset
-
- push cx ; save again
- mov si,[bx].pp ; get ptr again
- pop cx
- add cx,cx ; words
- cmp bx,offset bwnd ; bottom window?
- je getci6 ; e = yes
- sub si,cx ; top window, move back
- jnc getcir2 ; nc = still in buffer, continue
- mov si,twnd.bend ; else use end of buffer
- sub si,cx ; minus length of a piece
- inc si
- getcir2:mov twnd.pp,si ; update ptr
- dec twnd.lcnt ; decrement # of lines in buffer
- pop si
- pop cx
- clc ; make sure no carry
- ret
- getci6: ; bottom window
- add si,cx ; words, move back (bot buf = reverse)
- cmp si,bwnd.bend ; still in buffer?
- jb getci7 ; b = yes
- mov si,0 ; else use beginning of buffer
- getci7: mov bwnd.pp,si ; update ptr
- dec bwnd.lcnt ; decrement # of lines in buffer
- pop si
- pop cx
- clc ; make sure no carry
- ret
- getcirc endp
-
- ; prepares for scrolling by saving the top line in topbuf.
- scrprep proc near
- push ax ; save regs
- push es
- cmp al,cr ; carriage return?
- je scrpr3 ; yes, will never change line
- cmp al,lf ; outputting a linefeed?
- je scrpr2 ; yes, will change line
- mov ax,scrseg
- mov es,ax ; address screen segment
- test es:byte ptr [curlin],wrpend ; wrap pending?
- jz scrpr3 ; no, forget it
- mov ax,nvmseg
- mov es,ax
- test es:byte ptr [autwrp],1 ; auto-wrap mode?
- jz scrpr3 ; no, forget this
- ; about to change lines, see if bottom line
- scrpr2: mov ax,scrseg
- mov es,ax
- cmp es:byte ptr [csrlin],slen ; are we at the bottom?
- je scrpr4 ; yes, have to save line
- scrpr3: pop es ; get here if not saving line
- pop ax
- ret
- scrpr4: pop es ; restore registers
- pop ax
- ; alternate entry that doesn't check if we're on the bottom row.
- savtop: push ax ; save ax
- push bx
- push cx
- push si
- push di
- call kilcur ; kill cursor
- push es
- push ds
- mov ax,ds
- mov es,ax
- mov ax,scrseg
- mov ds,ax ; address screen segment
- mov si,ds:word ptr [l1ptr] ; get ptr to top line
- and si,0fffh ; only 12 bits are significant
- push si
- mov di,offset topline ; this is where it goes
- mov cx,swidth/2 ; # of words to copy, [RHW-5]
- cld
- rep movsw ; [RHW-4] get the top line
- pop si ; restore pointer
- add si,attoffs ; add offset of attributes
- mov cx,swidth/2 ; [RHW-5] # words to copy (swidth even)
- rep movsw ; [RHW-4] get the top line's attributes
- pop ds
- pop es ; restore segments
- mov srcseg,seg topline ; set segment of source
- mov si,offset topline ; set offset of source
- mov bx,offset twnd ; buffer structure pointer
- call putcirc ; put into circular buffer
- call rstcur
- pop di
- pop si
- pop cx
- pop bx
- pop ax ; restore character in ax
- ret ; and return
- scrprep endp
-
-
- ; get the screen's bottom line into the buffer in ax.
- getbot proc near
- push cx
- push si
- push di
- push es
- push ds
- push ax ; save destination on the stack
- call kilcur ; kill cursor
- push ds
- pop es
- mov si,scrseg
- mov ds,si
- mov si,ds:word ptr [llptr] ; get ptr to bottom line
- and si,0fffh ; only 12 bits are pointer
- pop di ; destination is on stack
- push si ; preserve pointer
- mov cx,swidth/2 ; # of words to copy [RHW-5]
- cld
- rep movsw ; [RHW-4] get the top line
- pop si ; get pointer back
- add si,attoffs ; this is where attributes are
- mov cx,swidth/2 ; [RHW-5] # words to copy
- rep movsw ; [RHW-4] get the top line
- pop ds ; restore segments
- pop es
- call rstcur ; restore cursor
- pop di
- pop si
- pop cx
- ret
- getbot endp
-
- ; handle the previous screen button...
-
- prvscr proc near
- mov cx,slen
- cmp twnd.lcnt,cx
- jge prvs1
- mov cx,twnd.lcnt
- prvs1: jcxz prvs2
- call prvlin
- loop prvs1
- prvs2: clc
- ret
- prvscr endp
-
- ; handle the next screen button...
-
- nxtscr proc near
- mov cx,slen
- cmp bwnd.lcnt,cx
- jge nxts1
- mov cx,bwnd.lcnt
- nxts1: jcxz nxts2
- call nxtlin
- loop nxts1
- nxts2: clc
- ret
- nxtscr endp
-
- ; save a screen by rolling them into a circular buffer.
- ; enter with ax/ circular buffer ptr, bx/ first line to get
- ; dx/ increment
-
- rolscr proc near
- mov cx,slen ; # of lines to save
- cmp cx,[bx].lcnt ; enough space left in this buffer?
- jbe rolsc0 ; be = enough
- mov cx,[bx].lcnt ; use only as many as we have
- jcxz rolscx ; z = none, so quit here
- rolsc0: shl dx,1 ; double increment for word ptr
- dec bx ; ptr starts at 0
- shl bx,1 ; convert to word ptr
- push es
- push ds
- pop es ; set es to data segment
- mov temp,0 ; save number of lines done
-
- rolsc1: push cx
- push dx
- push bx
- push ax
- push ds
- call kilcur ; kill cursor
- mov di,offset rlbuf
- mov ax,scrseg
- mov ds,ax ; address screen
- mov si,ds:[latofs+bx] ; get current line
- and si,0fffh ; ptr is in 12 bits
- push si ; save pointer
- mov cx,swidth/2 ; # of words to move, [RHW-5]
- rep movsw ; [RHW-4] get the line
- pop si ; restore pointer
- add si,attoffs ; where attributes start
- mov cx,swidth/2 ; # of bytes to move, [RHW-5]
- rep movsw ; [RHW-4] move attributes as well
- pop ds ; restore segment
- call rstcur ; restore cursor
- pop bx ; this is desired circ buffer ptr
- mov srcseg,seg rlbuf ; segment of source
- mov si,offset rlbuf ; offset of source
- call putcirc ; save in circular buffer
- mov ax,bx ; put buffer ptr back where it belongs
- pop bx ; get line pos back
- pop dx ; and increment
- pop cx ; don't forget counter
- add bx,dx ; move to next line
- inc temp
- loop rolsc1 ; loop thru all lines
- pop es
- rolscx: ret ; and return
- rolscr endp
-
- ; move screen down a line, get one previous line back
-
- prvlin proc near ; get the previous line back
- push ax
- push bx
- push dx
- cmp twnd.lcnt,0 ; any lines in top window?
- je prvli1 ; e = no, ignore request
- mov ax,offset botline ; place for bottom line
- call getbot ; fetch bottom line
- mov srcseg,seg botline ; segement of source
- mov si,offset botline ; offset of source
- mov bx,offset bwnd ; buffer structure pointer
- call putcirc ; save in circular buffer
- mov bx,offset twnd ; source structure
- push es
- mov di,seg topline
- mov es,di
- mov di,offset topline ; es:di is address of destination
- call getcirc ; try to get a line
- pop es
- jc prvli1 ; no more, just return
- call savpos ; save cursor position
- call kilcur ; turn off cursor
- mov dx,offset topdwn ; home, then reverse index
- call tmsg
- mov ax,offset topline ; point to data
- mov bx,0101H ; print line at top of screen
- mov dx,ax
- add dx,swidth
- call prlina ; print the line
- call rstcur
- call rstpos ; restore cursor position
- prvli1: pop dx
- pop bx
- pop ax
- clc
- ret ; and return
- prvlin endp
-
- ; move screen up a line, get one bottom line back
- nxtlin proc near
- push ax
- push bx
- push dx
- cmp bwnd.lcnt,0 ; any lines in bottom window?
- je nxtli1 ; e = no
- mov bx,offset bwnd ; source structure
- push es
- mov di,seg botline
- mov es,di
- mov di,offset botline ; es:di is address of destination
- call getcirc ; try to get a line
- pop es
- jc nxtli1 ; no more, just return
- call savtop ; save one line off of top
- call savpos ; save cursor position
- call kilcur ; turn off cursor
- mov dx,offset botup ; go to bottom, then scroll up a line
- call tmsg
- mov ax,offset botline ; point to data
- mov bx,0100H + slen ; print at bottom line
- mov dx,ax
- add dx,swidth
- call prlina ; print the line
- call rstcur ; turn cursor back on
- call rstpos ; restore cursor position
- nxtli1: pop dx
- pop bx
- pop ax
- clc
- ret
- nxtlin endp
-
- ; move screen up until no more saved in bottom buffer [jrd]
- nxtbot proc near
- push cx
- mov cx,bwnd.lcnt ; number of pages of scroll back memory
- nxtbot1:push cx
- call nxtlin
- pop cx
- loop nxtbot1 ; do all pages
- pop cx
- clc
- ret
- nxtbot endp
-
- nxttop proc near ; move to top of screen buffer memory [jrd]
- push cx
- mov cx,twnd.lcnt ; number of pages of scroll back memory
- nxttop1:push cx
- call prvlin
- pop cx
- loop nxttop1 ; do all pages
- pop cx
- clc
- ret
- nxttop endp
-
- ; save cursor position
- savpos proc near
- push di
- mov dx,offset curinq ; where is the cursor?
- call tmsg
- mov posbuf,escape ; put an escape in the buffer first
- mov di,offset posbuf+1
- savpo1: mov ah,8 ; read, no echo
- int dos
- cld
- cmp al,'R' ; end of report?
- je savpo2 ; yes
- stosb ; no, save it
- jmp short savpo1 ; and go on
- savpo2: mov al,'H' ; this ends the sequence when we send it
- stosb
- mov byte ptr [di],'$' ; need this to print it later
- pop di
- ret
- savpos endp
-
- ; restore the position saved by savpos
- rstpos proc near
- mov dx,offset posbuf
- call tmsg ; just print this
- ret
- rstpos endp
-
- ; kill cursor so it doesn't get saved along with real data
- kilcur proc near
- push ax
- push bx
- push cx
- push dx
- push si
- push es
- push di
- mov di,kcurfn
- int firmwr
- pop di
- pop es
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- kilcur endp
-
- ; restore the cursor
- rstcur proc near
- push ax
- push bx
- push cx
- push dx
- push si
- push es
- push di
- mov di,rcurfn
- int firmwr
- pop di
- pop es
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- rstcur endp
-
- ; print a ff-terminated line at most swidth long... Pass the line in ax.
- ; cursor position should be in bx.
- ; prlina writes attributes as well, which should be passed in dx.
- prlin proc near
- mov bp,2 ; print characters only
- jmp short prli1
- prlina: xor bp,bp ; 0 means print attributes as well
- prli1: push es ; this trashes es!!!
- push ax ; save regs
- push cx
- push es
- mov cx,scrseg
- mov es,cx ; address screen seg for a moment
- mov cl,es:byte ptr [rmargin] ; get max line length
- mov ch,0
- pop es ; address user's segment again
- push cx ; remember original length
- mov si,ax ; better place for ptr
- mov di,ax ; need it here for scan
- mov al,0ffh ; this marks the end of the line
- cld
- repne scasb ; look for the end
- jne prli2 ; not found
- inc cx ; account for pre-decrement
- prli2: neg cx
- pop ax ; get original length back
- add cx,ax
- ; add cx,swidth ; figure out length of line
- jcxz prli3 ; 0-length line, skip it
- mov ax,bp ; writing characters
- mov bp,ds ; wants segment here
- push bx
- push dx
- push si
- push di
- mov di,14H ; fast write to screen
- int firmwr
- pop di
- pop si
- pop dx
- pop bx
- prli3: pop cx ; restore registers
- pop ax
- pop es
- ret
- prlin endp
-
- ; action routines for keyboard translator.
- ; These are invoked by a jump instruction. Return carry clear for normal
- ; processing, return carry set for invoking Quit (kbdflg has transfer char).
-
- uparrw: mov al,'A' ; cursor keys
- jmp short comarr
- dnarrw: mov al,'B'
- jmp short comarr
- rtarr: mov al,'C'
- jmp short comarr
- lfarr: mov al,'D'
- comarr: push ax ; save final char
- mov al,escape ; Output an escape
- call sndhst ; Output, echo permitted
- push es ; save seg register
- mov ax,nvmseg ; fetch address of nvm
- mov es,ax ; put in segment reg
- test byte ptr es:[vt52mod],1 ; check bit zero
- pop es ; restore the seg register
- jnz comar1 ; nz = ansi mode
- jmp comar3 ; VT52 mode
- comar1: mov al,'[' ; Maybe this next?
- cmp ckeyflg,0 ; applications cursor mode?
- je comar2 ; e = no
- mov al,'O' ; applications mode
- comar2: call sndhst ; Output it (echo permitted)
- comar3: pop ax ; recover final char
- call sndhst ; Output to port (echo permitted)
- clc
- ret
-
- pf1: mov al,'P' ; keypad function keys
- jmp short compf
- pf2: mov al,'Q'
- jmp short compf
- pf3: mov al,'R'
- jmp short compf
- pf4: mov al,'S'
- compf: push ax ; save final char
- mov al,escape ; Output an escape
- call prtbout
- push es ; save seg register
- mov ax,nvmseg ; fetch address of nvm
- mov es,ax ; put in segment reg
- test byte ptr es:[vt52mod],1 ; check bit zero
- pop es ; restore the seg register
- jz compf1 ; z = VT52 mode
- mov al,'O' ; send an "O" in ansi mode
- call prtbout ; Output it
- compf1: pop ax ; Get the saved char back
- call prtbout ; Output to port
- clc
- ret
-
- kp0: mov al,'p' ; keypad numeric keys
- jmp short comkp
- kp1: mov al,'q'
- jmp short comkp
- kp2: mov al,'r'
- jmp short comkp
- kp3: mov al,'s'
- jmp short comkp
- kp4: mov al,'t'
- jmp short comkp
- kp5: mov al,'u'
- jmp short comkp
- kp6: mov al,'v'
- jmp short comkp
- kp7: mov al,'w'
- jmp short comkp
- kp8: mov al,'x'
- jmp short comkp
- kp9: mov al,'y'
- jmp short comkp
- kpminus:mov al,'m'
- jmp short comkp
- kpcoma: mov al,'l'
- jmp short comkp
- kpenter:mov al,'M'
- jmp short comkp
- kpdot: mov al,'n'
- comkp: cmp akeyflg,0 ; alternate keypad mode?
- jne comkp1 ; ne = yes
- sub al,'p'-'0' ; change to numeric codes
- jmp comkp3 ; and send just the ascii char
- comkp1: push ax ; save final char
- mov al,escape ; Output an escape
- call prtbout
- mov al,3fh ; Output the "?" in VT52 mode
- push es ; save seg register
- mov cx,nvmseg ; fetch address of nvm
- mov es,cx ; put in segment reg
- test byte ptr es:[vt52mod],1 ; check bit zero
- pop es ; restore the seg register
- jz comkp2 ; z = VT52 mode
- mov al,'O' ; Output the "O" in ansi mode
- comkp2: call prtbout
- pop ax ; recover final char
- comkp3: call prtbout ; send it
- clc
- ret
-
- snull proc near ; send a null byte
- mov al,0 ; the null
- call prtbout ; send without logging and local echo
- clc
- ret
- snull endp
-
- chrout: push es ; save segment
- push bx
- mov bx,nvmseg ; point to nvm
- mov es,bx ; set the segment
- test byte ptr es:[newlmod],1 ; check if we are set to new line
- pop bx
- pop es ; restore the segment register
- jz chrout1 ; just send the cr if bit is off
- call sndhst ; else send the carriage return first
- mov al,lf ; then the line-feed
- chrout1:call sndhst ; send char in al to serial port
- clc ; for keyboard translator
- ret ; can echo and log
-
-
- prtbout:mov ah,al ; output char with no echo
- call outchr ; outchr works with ah
- ret
-
- cdos: mov al,'P' ; Connect mode help screen items
- jmp short cmdcom
- cstatus:mov al,'S' ; these commands invoke Quit
- jmp short cmdcom
- cquit: mov al,'C' ; C = exit connection
- jmp short cmdcom
- cquery: mov al,'?' ; help
- jmp short cmdcom
- chang: mov al,'H' ; Hangup, drop DTR & RTS
- jmp short cmdcom
- cmdcom: mov kbdflg,al ; pass char to msster.asm via kbdflg
- stc ; signal that Quit is needed
- ret
-
- klogon proc near ; resume logging (if any)
- test flags.capflg,logses ; session logging enabled?
- jz klogn ; z = no, forget it
- or ourarg.flgs,capt ; turn on capture flag
- or argadr.flgs,capt ; permanent argument array too
- klogn: clc
- ret
- klogon endp
-
- klogof proc near ; suspend logging (if any)
- and argadr.flgs,not capt ; stop capturing
- and ourarg.flgs,not capt ; stop capturing
- klogo: clc
- ret
- klogof endp
- code ends
- end
-
-